﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using Framework.Core.Collections;
using Framework.Core.Dependency.Domain;
using log4net;

namespace Framework.Core.Dependency.Visitor
{
    internal class DependencyVisitor : IVisitor<Project>
    {
        private static readonly ILog Logger = LogManager.GetLogger(typeof(DependencyVisitor));
        private readonly IEnumerable<Project> buildProjects;
        private readonly IList<string> libs;
        private readonly ConcurrentHashset<Module> modulesNotFound = new ConcurrentHashset<Module>();

        public IEnumerable<Module> ModulesNotFound { get { return modulesNotFound; } }

        public DependencyVisitor(IEnumerable<Project> buildProjects, IList<string> libs)
        {
            this.buildProjects = buildProjects;
            this.libs = libs;
        }

        public void Visit(Project item)
        {
            foreach (var module in item.Modules)
            {
                Logger.InfoFormat("Find Dependencies for module : {0}", module.Name);
                var projectModule = buildProjects.FirstOrDefault(bp => IsProjectModule(bp, module));

                if (projectModule != null)
                {
                    item.AddDependency(projectModule);
                }
                
                else if (!libs.Any(x => ModulesEqualsToLib(x, module)))
                {
                    modulesNotFound.Add(module);
                }
            }
        }

        private static bool IsProjectModule(Project x, Module module)
        {
            var moduleToFind = Regex.Replace(module.Name,
                                             @"^.{0,2}interop\.",
                                             string.Empty,
                                             RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);

            return string.Equals(x.AssemblyName, moduleToFind, StringComparison.InvariantCultureIgnoreCase);
        }

        private static bool ModulesEqualsToLib(string x, Module module)
        {
            return string.Equals(Path.GetFileNameWithoutExtension(x), module.Name, StringComparison.InvariantCultureIgnoreCase);
        }
    }
}